﻿using System;
using System.Diagnostics;
using System.Globalization;

namespace Pyramid.Hardware
{
    /// <summary>
    /// Base implementation of the <see cref="Pyramid.Hardware.ILine"/>
    /// interface.
    /// </summary>
    /// <remarks>
    /// Holds the current state of the instance internally; this is updated
    /// by inheriting types by calling the SetSignal method.
    /// </remarks>
    public abstract class LineBase
        : ILine
    {
        /// <summary>
        /// The current output of the instance.
        /// </summary>
        private Trivalent signal;

        /// <summary>
        /// Update the current output of the instance and, if the new value is
        /// different from the existing value, raise the SignalChange event.
        /// </summary>
        /// <param name="newSignal">
        /// The new value to set for the Signal property.
        /// </param>
        protected void SetSignal(Trivalent newSignal)
        {
            if (this.signal == newSignal)
            {
                return;
            }

            Trivalent previousSignal = this.signal;

            this.signal = newSignal;

            EventHandler<SignalChangeEventArgs> signalChange = SignalChange;

            if (signalChange != null)
            {
                try
                {
                    signalChange(this, new SignalChangeEventArgs(previousSignal));
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Exception thrown in SignalChange handler: {0}", ex), "Setun.Hardware");
                    throw;
                }
            }
        }

        #region ILine Members

        /// <summary>
        /// Gets the current output of the line.
        /// </summary>
        public Trivalent Signal
        {
            get
            {
                return this.signal;
            }
        }

        /// <summary>
        /// Raised whenever the current output of the line changes.
        /// </summary>
        public event EventHandler<SignalChangeEventArgs> SignalChange;

        #endregion

        /// <summary>
        /// Returns the current output of the line as a string.
        /// </summary>
        /// <returns>
        /// A string containing the current output of the instance.
        /// </returns>
        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture, "[Line: {0}]", Signal);
        }
    }
}
